﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CommonClasses.Services
{
    public class SystemTimer : EcoExtensions.Model.BaseEcoService, ISystemTimer
    {
        private Timer timer;
        /// <summary>
        /// Список методов, которые подпасилсь на событие.
        /// </summary>
        private List<EventHandler> handlers = new List<EventHandler>();
        /// <summary>
        /// Список подписчиков, подготовленных к удалению.
        /// Будут удалены при следующем тике
        /// </summary>
        private List<EventHandler> delOrder = new List<EventHandler>();

        /// <summary>
        /// Список подписчиков, подготовленных к добавлению.
        /// Будут добавлены при следующем тике
        /// </summary>
        private List<EventHandler> addOrder = new List<EventHandler>();

        public SystemTimer()
        {
            timer = new Timer();
            timer.Tick += new EventHandler(timer_Tick);
        }

        #region ISystemTimer Members

        public bool Enabled
        { 
            get
            {
                return timer.Enabled;
            }
            set
            {
                timer.Enabled = value;
            }
        }

        public int Interval
        {
            get
            {
                return timer.Interval;
            }
            set
            {
                timer.Interval = value;
            }
        }

        public void Subscribe(EventHandler handler)
        {
            if (handler != null)
            {
                if (!handlers.Contains(handler) && !addOrder.Contains(handler))
                    addOrder.Add(handler);
                else
                    if (delOrder.Contains(handler))
                        delOrder.Remove(handler);
            }
        }

        public void DetachSubcribtion(EventHandler handler)
        {
            if (handler != null)
            {
                if (handlers.Contains(handler) && !delOrder.Contains(handler))
                    delOrder.Add(handler);
                else
                    if (addOrder.Contains(handler))
                        addOrder.Remove(handler);
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Обработать очереди добавления и удаления
        /// </summary>
        private void ProcessOrders()
        {
            handlers.AddRange(addOrder);
            addOrder.Clear();
            handlers.RemoveAll(handler => delOrder.Contains(handler));
            delOrder.Clear();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            ProcessOrders();

            var handlrs = new List<EventHandler>(handlers);
            foreach (var handler in handlrs)
            {
                if (!delOrder.Contains(handler))
                    handler(this, new EventArgs());
            }
        }

        #endregion
    }
}
